#include "logmanagement.h"
#include "ui_logmanagement.h"
#include <QSqlQuery>
#include <QFile>
#include <QTextStream>
#include <QDebug>
#include <QMessageBox>
#include <QFileDialog>
#include <QMenu>
#include <QPainter>
#include <QTimer>

bool LogManagement::s_encryptionEnabled = false;

LogLevelDelegate::LogLevelDelegate(QObject *parent) : QStyledItemDelegate(parent) {}

void LogLevelDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
                           const QModelIndex &index) const
{
    QStyleOptionViewItem opt = option;
    initStyleOption(&opt, index);

    QString level = index.data().toString();
    if (level == "INFO") {
        opt.palette.setColor(QPalette::Text, Qt::darkGreen);
    } else if (level == "WARNING") {
        opt.palette.setColor(QPalette::Text, Qt::darkYellow);
    } else if (level == "ERROR") {
        opt.palette.setColor(QPalette::Text, Qt::red);
    } else if (level == "CRITICAL") {
        opt.palette.setColor(QPalette::Text, Qt::darkRed);
        opt.font.setBold(true);
    }

    QStyledItemDelegate::paint(painter, opt, index);
}

LogManagement::LogManagement(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::LogManagement),
    m_logsModel(new QStandardItemModel(this)),
    m_logLevelDelegate(new LogLevelDelegate(this)),
    m_userManager(nullptr),
    m_refreshTimer(new QTimer(this)),
    m_rotationTimer(new QTimer(this)),
    m_encryptionEnabled(false),
    m_maxLogSizeMB(10),
    m_keepLogDays(30)
{
    ui->setupUi(this);

    // 修改刷新间隔为30秒
    m_refreshTimer->setInterval(30000);
    connect(m_refreshTimer, &QTimer::timeout, this, &LogManagement::refreshLogs);
    m_refreshTimer->start();

    initUI();
    initConnections();
    loadLogs();
    setupLogRotationTimer();
}

LogManagement::~LogManagement()
{
    delete ui;
    delete m_logLevelDelegate;
}

void LogManagement::log(const QString &content,
                      LogType type,
                      LogLevel level,
                      int userId,
                      int deviceId)
{
    QString typeStr;
    switch(type) {
        case SYSTEM_LOG: typeStr = "system"; break;
        case OPERATION_LOG: typeStr = "operation"; break;
        case ALARM_LOG: typeStr = "alarm"; break;
        case EXCEPTION_LOG: typeStr = "exception"; break;
    }

    QString levelStr;
    switch(level) {
        case LOG_INFO: levelStr = "INFO"; break;
        case LOG_WARNING: levelStr = "WARNING"; break;
        case LOG_ERROR: levelStr = "ERROR"; break;
        case LOG_CRITICAL: levelStr = "CRITICAL"; break;
    }

    QString escapedContent = content;
    escapedContent.replace("'", "''");

    QString sql = QString("INSERT INTO system_logs (timestamp, log_type, log_level, content, user_id, device_id) "
                         "VALUES ('%1', '%2', '%3', '%4', %5, %6)")
                         .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"))
                         .arg(typeStr)
                         .arg(levelStr)
                         .arg(escapedContent)
                         .arg(userId == -1 ? "NULL" : QString::number(userId))
                         .arg(deviceId == -1 ? "NULL" : QString::number(deviceId));

    DatabaseManager::instance()->sendRequest(sql);
}

void LogManagement::initUI()
{
    m_logsModel->setHorizontalHeaderLabels(
        {"日志ID", "时间", "类型", "等级", "内容", "用户ID", "设备ID"});
    ui->logsTableView->setModel(m_logsModel);
    ui->logsTableView->setItemDelegateForColumn(3, m_logLevelDelegate);
    ui->logsTableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Interactive);
    ui->logsTableView->setContextMenuPolicy(Qt::CustomContextMenu);
    ui->logsTableView->setSelectionBehavior(QAbstractItemView::SelectRows);

    ui->startDateTimeEdit->setDateTime(QDateTime::currentDateTime().addDays(-7));
    ui->endDateTimeEdit->setDateTime(QDateTime::currentDateTime());

    ui->typeComboBox->addItem("所有类型", "");
    ui->typeComboBox->addItem("系统日志", "system");
    ui->typeComboBox->addItem("操作日志", "operation");
    ui->typeComboBox->addItem("告警日志", "alarm");
    ui->typeComboBox->addItem("异常日志", "exception");

    ui->levelComboBox->addItem("所有等级", "");
    ui->levelComboBox->addItem("信息", "INFO");
    ui->levelComboBox->addItem("警告", "WARNING");
    ui->levelComboBox->addItem("错误", "ERROR");
    ui->levelComboBox->addItem("严重", "CRITICAL");
}

void LogManagement::initConnections()
{
    connect(ui->queryButton, &QPushButton::clicked, this, &LogManagement::onQueryButtonClicked);
    connect(ui->exportButton, &QPushButton::clicked, this, &LogManagement::onExportButtonClicked);
    connect(ui->deleteButton, &QPushButton::clicked, this, &LogManagement::onDeleteButtonClicked);
    connect(ui->clearButton, &QPushButton::clicked, this, &LogManagement::onClearButtonClicked);
    connect(ui->logsTableView, &QTableView::customContextMenuRequested,
            this, &LogManagement::showContextMenu);
    connect(ui->searchLineEdit, &QLineEdit::textChanged,
            this, &LogManagement::onSearchTextChanged);
    connect(m_refreshTimer, &QTimer::timeout, this, &LogManagement::refreshLogs);
    m_refreshTimer->start(5000);
}

void LogManagement::loadLogs()
{
    // 1. 权限检查
    if (m_userManager && !m_userManager->getCurrentUserRole().contains("admin")) {
        QMessageBox::warning(this, "权限不足", "只有管理员可以查看日志");
        return;
    }

    // 2. 防止过快刷新（最少5秒间隔）
    static QDateTime lastRefresh;
    if(lastRefresh.isValid() && lastRefresh.msecsTo(QDateTime::currentDateTime()) < 5000) {
        return;
    }
    lastRefresh = QDateTime::currentDateTime();

    // 3. 准备查询条件
    m_logsModel->removeRows(0, m_logsModel->rowCount());

    QDateTime startTime = ui->startDateTimeEdit->dateTime();
    QDateTime endTime = ui->endDateTimeEdit->dateTime();
    QString logType = ui->typeComboBox->currentData().toString();
    QString logLevel = ui->levelComboBox->currentData().toString();
    QString searchText = ui->searchLineEdit->text();

    // 4. 构建查询语句（只查新日志）
    QString queryStr = QString("SELECT log_id, timestamp, log_type, log_level, content, user_id, device_id "
                            "FROM system_logs WHERE timestamp BETWEEN '%1' AND '%2'")
                            .arg(startTime.toString("yyyy-MM-dd hh:mm:ss"))
                            .arg(endTime.toString("yyyy-MM-dd hh:mm:ss"));

    if (!logType.isEmpty()) {
        queryStr += QString(" AND log_type = '%1'").arg(logType);
    }
    if (!logLevel.isEmpty()) {
        queryStr += QString(" AND log_level = '%1'").arg(logLevel);
    }
    if (!searchText.isEmpty()) {
        queryStr += QString(" AND content LIKE '%%1%'").arg(searchText.replace("'","''"));
    }
    queryStr += " ORDER BY timestamp DESC LIMIT 1000";

    // 5. 执行查询
    QString response = DatabaseManager::instance()->sendRequest(queryStr);

    // 6. 错误处理
    if(response.startsWith("Error:")) {
        qWarning() << "日志查询失败:" << response;
        if(!response.contains("Query too frequent")) { // 不显示频率限制错误
            QMessageBox::critical(this, "错误", "查询日志失败: " + response.mid(6));
        }
        return;
    }

    // 7. 处理结果
    QStringList rows = response.split("\n", QString::SkipEmptyParts);
    foreach(const QString &row, rows) {
        QStringList columns = row.split("|", QString::SkipEmptyParts);
        if(columns.size() < 7) continue;

        // 8. 解密内容（如果启用加密）
        QString content = columns[4];
        if (m_encryptionEnabled) {
            decryptLogContent(content);
        }

        // 9. 添加到模型
        QList<QStandardItem*> rowItems;
        rowItems << new QStandardItem(columns[0].trimmed())
                << new QStandardItem(columns[1].trimmed())
                << new QStandardItem(columns[2].trimmed())
                << new QStandardItem(columns[3].trimmed())
                << new QStandardItem(content)
                << new QStandardItem(columns[5].trimmed())
                << new QStandardItem(columns[6].trimmed());
        m_logsModel->appendRow(rowItems);
    }
}

void LogManagement::encryptLogContent(QString &content)
{
    if(m_encryptionEnabled) {
        QByteArray data = content.toUtf8();
        for(int i = 0; i < data.size(); ++i) {
            data[i] = data[i] ^ 0x55;
        }
        content = QString::fromLatin1(data.toBase64());
    }
}

void LogManagement::decryptLogContent(QString &content)
{
    if(m_encryptionEnabled) {
        QByteArray data = QByteArray::fromBase64(content.toLatin1());
        for(int i = 0; i < data.size(); ++i) {
            data[i] = data[i] ^ 0x55;
        }
        content = QString::fromUtf8(data);
    }
}

void LogManagement::onQueryButtonClicked()
{
    // 重置查询时间范围
    static QDateTime lastQueryTime;
    if (lastQueryTime.isValid() && lastQueryTime.secsTo(QDateTime::currentDateTime()) < 5) {
        QMessageBox::information(this, "提示", "请勿频繁刷新");
        return;
    }
    lastQueryTime = QDateTime::currentDateTime();

    refreshLogs();
}

void LogManagement::onExportButtonClicked()
{
    if(!checkUserPermission()) {
        QMessageBox::warning(this, "警告", "您没有导出日志的权限");
        return;
    }

    QString fileName = QFileDialog::getSaveFileName(
        this, "导出日志", "", "CSV文件 (*.csv);;文本文件 (*.txt)");

    if(fileName.isEmpty()) return;

    if(fileName.endsWith(".csv")) {
        exportToFile(fileName, "CSV");
    } else {
        exportToFile(fileName, "TXT");
    }
}

void LogManagement::exportToFile(const QString &fileName, const QString &format)
{
    QFile file(fileName);
    if(!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
        QMessageBox::critical(this, "错误", "无法创建文件");
        return;
    }

    QTextStream out(&file);

    for(int col = 0; col < m_logsModel->columnCount(); ++col) {
        if(format == "CSV") {
            out << "\"" << m_logsModel->horizontalHeaderItem(col)->text() << "\"";
            if(col < m_logsModel->columnCount() - 1) out << ",";
        } else {
            out << m_logsModel->horizontalHeaderItem(col)->text() << "\t";
        }
    }
    out << "\n";

    for(int row = 0; row < m_logsModel->rowCount(); ++row) {
        for(int col = 0; col < m_logsModel->columnCount(); ++col) {
            QString text = m_logsModel->item(row, col)->text();
            if(format == "CSV") {
                out << "\"" << text << "\"";
                if(col < m_logsModel->columnCount() - 1) out << ",";
            } else {
                out << text << "\t";
            }
        }
        out << "\n";
    }

    file.close();
    QMessageBox::information(this, "成功", "日志导出完成");
}

void LogManagement::onDeleteButtonClicked()
{
    if(!checkUserPermission()) {
        QMessageBox::warning(this, "警告", "您没有删除日志的权限");
        return;
    }

    QModelIndexList selected = ui->logsTableView->selectionModel()->selectedRows();
    if(selected.isEmpty()) {
        QMessageBox::warning(this, "警告", "请选择要删除的日志");
        return;
    }

    int logId = m_logsModel->item(selected.first().row(), 0)->text().toInt();

    QMessageBox::StandardButton reply;
    reply = QMessageBox::question(this, "确认删除",
                                "确定要删除选中的日志吗？此操作不可撤销！",
                                QMessageBox::Yes | QMessageBox::No);

    if(reply == QMessageBox::Yes) {
        QString sql = QString("DELETE FROM system_logs WHERE log_id = %1").arg(logId);
        QString response = DatabaseManager::instance()->sendRequest(sql);

        if(response.contains("successfully")) {
            loadLogs();
            QMessageBox::information(this, "成功", "日志已删除");
        } else {
            QMessageBox::critical(this, "错误", "删除失败: " + response);
        }
    }
}

bool LogManagement::checkUserPermission()
{
    if(m_userManager && m_userManager->getCurrentUserRole().contains("admin")) {
        return true;
    }
    return false;
}

void LogManagement::showContextMenu(const QPoint &pos)
{
    QMenu menu(this);

    QAction* encryptAction = menu.addAction("日志加密");
    encryptAction->setCheckable(true);
    encryptAction->setChecked(m_encryptionEnabled);
    connect(encryptAction, &QAction::triggered,
            this, &LogManagement::onEncryptActionTriggered);

    menu.addSeparator();
    QAction* exportAction = menu.addAction("导出选中日志");
    QAction* deleteAction = menu.addAction("删除选中日志");

    QModelIndex index = ui->logsTableView->indexAt(pos);
    if(!index.isValid()) {
        exportAction->setEnabled(false);
        deleteAction->setEnabled(false);
    } else {
        deleteAction->setEnabled(checkUserPermission());
    }

    QAction *selectedAction = menu.exec(ui->logsTableView->viewport()->mapToGlobal(pos));

    if(selectedAction == exportAction) {
        onExportButtonClicked();
    } else if(selectedAction == deleteAction) {
        onDeleteButtonClicked();
    }
}

void LogManagement::refreshLogs()
{
    loadLogs();
}

void LogManagement::onSearchTextChanged(const QString &text)
{
    Q_UNUSED(text);
    loadLogs();
}

void LogManagement::onClearButtonClicked()
{
    if(!checkUserPermission()) {
        QMessageBox::warning(this, "警告", "您没有清空日志的权限");
        return;
    }

    QMessageBox::StandardButton reply;
    reply = QMessageBox::question(this, "确认清空",
                                "确定要清空所有日志吗？此操作不可撤销！",
                                QMessageBox::Yes | QMessageBox::No);

    if(reply == QMessageBox::Yes) {
        QString response = DatabaseManager::instance()->sendRequest("DELETE FROM system_logs");

        if(response.contains("successfully")) {
            loadLogs();
            QMessageBox::information(this, "成功", "日志已清空");
        } else {
            QMessageBox::critical(this, "错误", "清空失败: " + response);
        }
    }
}

void LogManagement::setUserManager(UserManager *userManager)
{
    m_userManager = userManager;
    bool isAdmin = checkUserPermission();
    ui->deleteButton->setEnabled(isAdmin);
    ui->clearButton->setEnabled(isAdmin);
}

void LogManagement::setupLogRotationTimer()
{
    m_rotationTimer = new QTimer(this);
    m_rotationTimer->setInterval(24 * 60 * 60 * 1000);
    connect(m_rotationTimer, &QTimer::timeout,
            this, &LogManagement::performLogRotation);
    m_rotationTimer->start();
    qDebug() << "日志轮转定时器已启动，间隔：" << m_rotationTimer->interval() << "毫秒";
}

void LogManagement::performLogRotation()
{
    QString response = DatabaseManager::instance()->sendRequest(
        "PRAGMA page_count * PRAGMA page_size / (1024 * 1024)");

    if(!response.startsWith("Error:")) {
        int dbSizeMB = response.toInt();
        if(dbSizeMB > m_maxLogSizeMB) {
            QDateTime cutoff = QDateTime::currentDateTime().addDays(-m_keepLogDays);
            QString deleteResponse = DatabaseManager::instance()->sendRequest(
                QString("DELETE FROM system_logs WHERE timestamp < '%1'")
                .arg(cutoff.toString("yyyy-MM-dd hh:mm:ss")));

            if(deleteResponse.contains("successfully")) {
                qInfo() << "日志轮转完成，删除了早于" << cutoff.toString("yyyy-MM-dd") << "的日志";
            } else {
                qWarning() << "日志删除失败:" << deleteResponse;
            }
        }
    } else {
        qWarning() << "数据库大小检查失败:" << response;
    }
}

void LogManagement::onEncryptActionTriggered()
{
    m_encryptionEnabled = !m_encryptionEnabled;
    QAction* action = qobject_cast<QAction*>(sender());
    if(action) {
        action->setChecked(m_encryptionEnabled);
    }
    QMessageBox::information(this, "日志加密",
                           QString("日志加密功能%1").arg(m_encryptionEnabled ? "已启用" : "已禁用"));
    loadLogs();
}

void LogManagement::onAuditActionTriggered()
{
    if (!checkUserPermission()) {
        QMessageBox::warning(this, "权限不足", "只有管理员可以执行日志审计");
        return;
    }

    QString auditReport;
    QString errorResponse = DatabaseManager::instance()->sendRequest(
        "SELECT COUNT(*) FROM system_logs WHERE log_level IN ('ERROR', 'CRITICAL')");

    if(!errorResponse.startsWith("Error:")) {
        auditReport += QString("发现 %1 条异常日志\n").arg(errorResponse.toInt());
    }

    QString unauthorizedResponse = DatabaseManager::instance()->sendRequest(
        "SELECT COUNT(*) FROM system_logs "
        "WHERE log_type='operation' AND content LIKE '%unauthorized%'");

    if(!unauthorizedResponse.startsWith("Error:")) {
        auditReport += QString("发现 %1 次未授权访问尝试\n").arg(unauthorizedResponse.toInt());
    }

    QMessageBox::information(this, "日志审计报告",
                           auditReport.isEmpty() ? "未发现异常情况" : auditReport);
}
